# -*- encoding: utf-8 -*-

EPC = 16
ESP = 17
EBP = 18

class Memory(object):

    """ Classe gérant la mémoire que l'on souhaite simuler. """

    def __init__ (self):
        self.__ramSize = 256
        self.__ram = [0 for _ in range(self.__ramSize)]
        self.__registers = [0 for _ in range(32)]
        self.__registers[ESP] = 0
        self.__flags = {
            'C' : False,
            'N' : False,
            'O' : False,
            'Z' : False
            }

    def getFlag (self, flag):
        return self.__flags[flag]

    def setFlag (self, flag, value):
        self.__flags[flag] = value

    def getRamAt (self, addr):
        if  addr < len(self.__ram):
            return self.__ram[addr]
        else:
            raise Exception("Address " + str(addr) + " out of memory.")

    def setRamAt (self, addr, newVal):
        if addr < len(self.__ram):
            self.__ram[addr] = newVal % 256
        else:
            raise Exception("Address " + str(addr) + " out of memory.")

    def getRegister (self, num):
        return self.__registers[num]

    def setRegister (self, num, newVal):
        self.__registers[num] = newVal % 256
        return self

    def getRamSize (self):
        return self.__ramSize

    def __str__ (self):
        esp = self.getRegister(ESP)
        return "\n".join([
                "RAM : [B] " + " ".join([str(self.getRamAt(i)) for i in range(esp, 256)]) + " [T]",
                "REG : " + " ".join([str(self.getRegister(i)) for i in range(0, 16)]),
                "EPC = {0:d}, ESP = {1:d}, EBP = {2:d}".format(self.getRegister(EPC), self.getRegister(ESP), self.getRegister(EBP)),
                "N = {0:d}, C = {1:d}, Z = {2:d}, O = {3:d}".format(self.getFlag('N'), self.getFlag('C'), self.getFlag('Z'), self.getFlag('O'))
                ])
